use calamine::{Reader, Xlsx, Data};
use slint::SharedString;
use std::path::{Path, PathBuf};
use xlsxwriter::{Workbook, XlsxError};
use slint::Weak;

slint::slint! {
    import { MainWindow } from "views/MainWindow.slint";
}
slint::slint! {
    import { Toast } from "views/Toast.slint";
}
fn split_excel(input_path: &str, output_dir: Option<&str>, row_count: usize) -> Result<(), Box<dyn std::error::Error>> {
    let mut workbook: Xlsx<_> = calamine::open_workbook(input_path)?;
    let sheet_names = workbook.sheet_names().to_owned();

    let range = workbook.worksheet_range(&sheet_names[0])?;
    let mut rows = range.rows();

    let header: Vec<Data> = match rows.next() {
        Some(row) => row.iter().cloned().collect(),
        None => return Err("Excel 文件为空".into()),
    };

    let input_path = Path::new(input_path);
    let output_dir = match output_dir {
        Some(dir) => PathBuf::from(dir),
        None => input_path.parent().unwrap_or(Path::new(".")).to_path_buf(),
    };

    let mut current_row = 0;
    let mut file_index = 1;
    let mut current_workbook: Option<Workbook> = None;
    let mut current_sheet = None;

    for row in rows {
        if current_row % row_count == 0 {
            if let Some(wb) = current_workbook.take() {
                wb.close()?;
            }

            let file_stem = input_path.file_stem().unwrap().to_string_lossy();
            let output_path = output_dir.join(format!("{}_{}.xlsx", file_stem, file_index));
            current_workbook = Some(Workbook::new(output_path.to_str().unwrap())?);
            current_sheet = Some(current_workbook.as_ref().unwrap().add_worksheet(None)?);
            file_index += 1;

            // 写入表头
            for (col, cell) in header.iter().enumerate() {
                let value = get_cell_vallue(cell);
                current_sheet.as_mut().unwrap().write_string(0, col as u16, &value, None)?;
            }
        }

        // 写入数据行
        for (col, cell) in row.iter().enumerate() {
            let value = get_cell_vallue(cell);
            current_sheet.as_mut().unwrap().write_string(
                (current_row % row_count + 1) as u32,
                col as u16,
                &value,
                None,
            )?;
        }

        current_row += 1;
    }

    if let Some(wb) = current_workbook {
        wb.close()?;
    }

    Ok(())
}

fn get_cell_vallue(cell: &Data) -> String {
    let value = match cell {
        Data::String(s) => s.to_string(),
        Data::Float(f) => f.to_string(),
        Data::Int(i) => i.to_string(),
        Data::Bool(b) => if *b { "TRUE" } else { "FALSE" }.parse().unwrap(),
        Data::Empty => "".parse().unwrap(),
        Data::DateTime(dt) => dt.to_string(),
        Data::Error(e) => e.to_string(),
        Data::DateTimeIso(dt) => dt.to_string(),
        Data::DurationIso(d) => d.to_string(),
        _ => "".parse().unwrap(),
    };
    value
}

fn show_toast() {
    let toast = Toast::new().unwrap();
    let toast_weak = toast.as_weak();
    toast.on_closed(move || {
        toast_weak.unwrap().hide();
    });
    toast.show().unwrap();
}

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let main_window = MainWindow::new()?;
    let weak = main_window.as_weak();

    main_window.on_select_file_clicked(move || {
        let window = weak.unwrap();
        if let Some(path) = rfd::FileDialog::new()
            .add_filter("Excel Files", &["xlsx"])
            .pick_file()
        {
            window.set_excel_path(path.to_string_lossy().into_owned().into());
        }
    });

    let weak = main_window.as_weak();
    main_window.on_select_output_dir_clicked(move || {
        let window = weak.unwrap();
        if let Some(path) = rfd::FileDialog::new()
            .pick_folder()
        {
            window.set_output_dir(path.to_string_lossy().into_owned().into());
        }
    });

    let weak = main_window.as_weak();
    main_window.on_row_count_edited(move |row_count| {
        weak.unwrap().set_row_count(row_count.into());
    });

    let weak = main_window.as_weak();
    main_window.on_split_clicked(move || {
        let window = weak.unwrap();
        let excel_path = window.get_excel_path().to_string();
        let output_dir = window.get_output_dir().to_string();
        let row_count1 = window.get_row_count().to_string();
        let row_count = row_count1.parse::<usize>().unwrap();

        let output_dir = if output_dir.is_empty() {
            None
        } else {
            Some(output_dir.as_str())
        };

        if let Err(e) = split_excel(&excel_path, output_dir, row_count) {
            eprintln!("拆分失败: {}", e);
        } else {
            show_toast();
        }
    });

    main_window.run()?;
    Ok(())
}
